from .redis_db import RedisDB
import redis
from . import const

GLOBAL_LOCK = "get_runner_info"


class RedisRunnerInfo(RedisDB):


    def init_runner_info(self, uuid):
        runner_info = {
            "uuid": uuid,
            "case-control-status": const.CASE_STATUS_RUNNING,
            "runner-status": const.RUNNER_STATUS_INIT,
            "case-status": const.CASE_STATUS_INIT,
        }
        conn = redis.Redis(connection_pool=self.conn_pool)
        runner_key_name = f"{const.RUNNER_KEY}-{uuid}"
        conn.hmset(runner_key_name, runner_info)
        # runner timeout
        conn.expire(runner_key_name, const.RUNNER_TIMEOUT)

    def update_runner_info(self, uuid, info: dict):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        for k, v in info.items():
            if conn.hget(key_name, k) != v:
                conn.hset(key_name, k, v)
        self.release_lock(GLOBAL_LOCK, lock)

    def get_runner_info(self, uuid) -> dict:
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        runner_info = {}
        conn = redis.Redis(connection_pool=self.conn_pool)
        hash_all = conn.hgetall(key_name)
        if hash_all:
            for k, v in hash_all.items():
                runner_info[k.decode()] = v.decode()
        self.release_lock(GLOBAL_LOCK, lock)
        return runner_info

    def delete_runner_info(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.delete(key_name)
        self.release_lock(GLOBAL_LOCK, lock)

    def sync_case_status(self, uuid) -> str:
        '''
        同步用例状态
        return: case_status 同步之后的case状态
        '''
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        case_status = conn.hget(key_name, "case-status")
        case_control_status = conn.hget(key_name, "case-control-status")
        if case_status != case_control_status:
            conn.hset(key_name, "case-status", case_control_status)
        self.release_lock(GLOBAL_LOCK, lock)
        sync_status = case_control_status.decode() if case_status else None
        return sync_status

    def pause_case(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-control-status", const.CASE_STATUS_PAUSED)
        self.release_lock(GLOBAL_LOCK, lock)

    def cancel_case(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-control-status", const.CASE_STATUS_CANCELLED)
        self.release_lock(GLOBAL_LOCK, lock)

    def resume_case(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-control-status", const.CASE_STATUS_RUNNING)
        self.release_lock(GLOBAL_LOCK, lock)

    def end_case(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-control-status", const.CASE_STATUS_FORCE_END)
        self.release_lock(GLOBAL_LOCK, lock)

    def set_runner_complete(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "runner-status", const.RUNNER_STATUS_COMPLETED)
        self.release_lock(GLOBAL_LOCK, lock)
    
    def set_case_complete(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-status", const.CASE_STATUS_COMPLETED)
        self.release_lock(GLOBAL_LOCK, lock)

    def set_case_running(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-status", const.CASE_STATUS_RUNNING)
        self.release_lock(GLOBAL_LOCK, lock)
    
    def set_case_end(self, uuid):
        key_name = f"{const.RUNNER_KEY}-{uuid}"
        lock = self.acquire_lock(GLOBAL_LOCK)
        conn = redis.Redis(connection_pool=self.conn_pool)
        conn.hset(key_name, "case-status", const.CASE_STATUS_FORCE_END)
        self.release_lock(GLOBAL_LOCK, lock)
    